"use client"

import { useState, useCallback, useEffect, useMemo } from "react"
import { useRouter } from "next/navigation"
import ReactFlow, {
  Node,
  Edge,
  addEdge,
  Background,
  Controls,
  MiniMap,
  Connection,
  useNodesState,
  useEdgesState,
  MarkerType,
  Panel,
} from "reactflow"
import "reactflow/dist/style.css"

import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
import { ScrollArea } from "@/components/ui/scroll-area"
import { Badge } from "@/components/ui/badge"
import { Separator } from "@/components/ui/separator"
import { useToast } from "@/hooks/use-toast"
import {
  Save,
  Play,
  Brain,
  Eye,
  Edit3,
  Info,
  Code2,
} from "lucide-react"

import { CustomNode } from "@/components/flow-nodes/custom-node"
import { NodeParameterEditor, ParameterList } from "@/components/node-parameter-editor"
import { agentComponentConfigs, iconMap, type NodeConfig } from "@/lib/node-configs"
import { generateLangGraphCodeV2 } from "@/lib/langgraph-generator-v2"
import { useModelProviders, providersToOptions } from "@/hooks/use-model-providers"

const nodeTypes = {
  custom: CustomNode,
}

interface AgentBuilderV3Props {
  agentId?: string
  mode?: "edit" | "view"
}

export function AgentBuilderV3({ agentId, mode = "edit" }: AgentBuilderV3Props) {
  const router = useRouter()
  const { toast } = useToast()
  const [agentName, setAgentName] = useState("未命名 Agent")
  const [selectedNodeId, setSelectedNodeId] = useState<string | null>(null)
  const [isLoading, setIsLoading] = useState(true)
  const [mounted, setMounted] = useState(false)
  const [viewMode, setViewMode] = useState<"edit" | "view">(mode)

  const [nodes, setNodes, onNodesChange] = useNodesState([])
  const [edges, setEdges, onEdgesChange] = useEdgesState([])

  // 加载已配置的模型供应商
  const { providers } = useModelProviders()

  useEffect(() => {
    setMounted(true)
  }, [])

  useEffect(() => {
    if (!mounted) return

    setIsLoading(true)

    // 首先尝试从 sessionStorage 恢复状态（从代码查看页返回时）
    const savedNodes = sessionStorage.getItem("agent_builder_nodes")
    const savedEdges = sessionStorage.getItem("agent_builder_edges")
    const savedName = sessionStorage.getItem("agent_builder_name")

    if (savedNodes && savedEdges) {
      // 恢复状态
      try {
        const parsedNodes = JSON.parse(savedNodes)
        const parsedEdges = JSON.parse(savedEdges)

        // 恢复 onDelete 回调
        const nodesWithCallback = parsedNodes.map((node: Node) => ({
          ...node,
          data: {
            ...node.data,
            onDelete: handleDeleteNode,
          },
        }))

        setNodes(nodesWithCallback)
        setEdges(parsedEdges)
        if (savedName) setAgentName(savedName)

        // 清理 sessionStorage
        sessionStorage.removeItem("agent_builder_nodes")
        sessionStorage.removeItem("agent_builder_edges")
        sessionStorage.removeItem("agent_builder_name")
      } catch (error) {
        console.error("Failed to restore agent builder state:", error)
      } finally {
        setIsLoading(false)
      }
    } else if (agentId) {
      // 从 API 加载
      fetch(`/api/agents?id=${agentId}`)
        .then((res) => res.json())
        .then((result) => {
          if (result.success && result.data) {
            const agent = result.data
            setAgentName(agent.name)

            // Convert old format to React Flow format
            const flowNodes: Node[] =
              agent.components?.map((comp: any) => ({
                id: comp.id,
                type: "custom",
                position: { x: comp.x || 0, y: comp.y || 0 },
                data: {
                  label: comp.label,
                  type: comp.type,
                  iconName: comp.config?.iconName,
                  config: comp.config,
                  parameterValues: comp.config?.parameterValues || {},
                  onDelete: handleDeleteNode,
                },
              })) || []

            const flowEdges: Edge[] =
              agent.edges?.map((edge: any) => ({
                id: edge.id,
                source: edge.source,
                target: edge.target,
                type: "smoothstep",
                animated: true,
                markerEnd: {
                  type: MarkerType.ArrowClosed,
                },
              })) || []

            setNodes(flowNodes)
            setEdges(flowEdges)
          }
        })
        .catch((error) => {
          console.error("Failed to load agent:", error)
          toast({
            title: "加载失败",
            description: "无法加载 Agent 数据",
            variant: "destructive",
          })
        })
        .finally(() => {
          setIsLoading(false)
        })
    } else {
      setIsLoading(false)
    }
  }, [agentId, mounted])

  const onConnect = useCallback(
    (params: Connection) => {
      setEdges((eds) =>
        addEdge(
          {
            ...params,
            type: "smoothstep",
            animated: true,
            markerEnd: {
              type: MarkerType.ArrowClosed,
            },
          },
          eds,
        ),
      )
    },
    [setEdges],
  )

  const onDragOver = useCallback((event: React.DragEvent) => {
    event.preventDefault()
    event.dataTransfer.dropEffect = "move"
  }, [])

  const onDrop = useCallback(
    (event: React.DragEvent) => {
      event.preventDefault()

      const nodeConfigStr = event.dataTransfer.getData("application/reactflow")
      if (!nodeConfigStr) return

      const nodeConfig: NodeConfig = JSON.parse(nodeConfigStr)

      const position = {
        x: event.clientX - 200,
        y: event.clientY - 100,
      }

      const newNode: Node = {
        id: `${nodeConfig.type}-${Date.now()}`,
        type: "custom",
        position,
        data: {
          label: nodeConfig.label,
          type: nodeConfig.type,
          iconName: nodeConfig.iconName,
          config: nodeConfig,
          parameterValues: {},
          onDelete: handleDeleteNode,
        },
      }

      setNodes((nds) => nds.concat(newNode))
      toast({
        title: "组件已添加",
        description: `${nodeConfig.label} 已添加到画布`,
      })
    },
    [setNodes, toast],
  )

  const handleDeleteNode = useCallback(
    (nodeId: string) => {
      setNodes((nds) => nds.filter((node) => node.id !== nodeId))
      setEdges((eds) => eds.filter((edge) => edge.source !== nodeId && edge.target !== nodeId))
      if (selectedNodeId === nodeId) {
        setSelectedNodeId(null)
      }
      toast({
        title: "组件已删除",
        description: "组件及其连接已从画布中移除",
      })
    },
    [setNodes, setEdges, selectedNodeId, toast],
  )

  const handleSave = async () => {
    const agentData = {
      name: agentName,
      components: nodes.map((node) => ({
        id: node.id,
        type: node.data.type,
        label: node.data.label,
        x: node.position.x,
        y: node.position.y,
        config: {
          iconName: node.data.iconName,
          parameterValues: node.data.parameterValues,
        },
      })),
      edges: edges.map((edge) => ({
        id: edge.id,
        source: edge.source,
        target: edge.target,
      })),
    }

    try {
      if (agentId) {
        // 更新现有 Agent
        const response = await fetch("/api/agents", {
          method: "PUT",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({
            id: agentId,
            ...agentData,
          }),
        })

        const result = await response.json()

        if (result.success) {
          toast({
            title: "保存成功",
            description: "Agent 已更新",
          })
        } else {
          throw new Error(result.error || "保存失败")
        }
      } else {
        // 创建新 Agent
        const response = await fetch("/api/agents", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify(agentData),
        })

        const result = await response.json()

        if (result.success) {
          toast({
            title: "保存成功",
            description: "新 Agent 已创建",
          })
          // 可选：导航到编辑页面
          if (result.data?.id) {
            router.push(`/dashboard/agents/edit/${result.data.id}`)
          }
        } else {
          throw new Error(result.error || "保存失败")
        }
      }
    } catch (error) {
      console.error("Failed to save agent:", error)
      toast({
        title: "保存失败",
        description: error instanceof Error ? error.message : "无法保存 Agent",
        variant: "destructive",
      })
    }
  }

  const handleTest = () => {
    toast({
      title: "测试运行中",
      description: "Agent 正在执行测试...",
    })
    setTimeout(() => {
      toast({
        title: "测试完成",
        description: "Agent 执行成功",
      })
    }, 2000)
  }

  const handleViewGeneratedCode = () => {
    // 生成分层架构代码（使用V2版本）
    const code = generateLangGraphCodeV2(nodes, edges, agentComponentConfigs)

    // 保存当前 Agent Builder 状态，以便返回时恢复
    sessionStorage.setItem("agent_builder_nodes", JSON.stringify(nodes))
    sessionStorage.setItem("agent_builder_edges", JSON.stringify(edges))
    sessionStorage.setItem("agent_builder_name", agentName)

    // 保存生成的代码到 sessionStorage
    sessionStorage.setItem("langgraph_generated_code_v2", JSON.stringify(code))
    sessionStorage.setItem("langgraph_source_type", "agent")
    sessionStorage.setItem("langgraph_source_name", agentName)

    // 导航到代码查看页面
    router.push("/dashboard/code-viewer")

    toast({
      title: "代码已生成",
      description: `已生成包含 ${code.layers.length} 层架构、${code.summary.fileCount} 个文件`,
    })
  }

  const onDragStart = (event: React.DragEvent, config: NodeConfig) => {
    event.dataTransfer.setData("application/reactflow", JSON.stringify(config))
    event.dataTransfer.effectAllowed = "move"
  }

  const selectedNode = useMemo(() => {
    return nodes.find((node) => node.id === selectedNodeId)
  }, [nodes, selectedNodeId])

  const selectedNodeConfig = useMemo(() => {
    if (!selectedNode) return null
    const config = agentComponentConfigs.find((config) => config.type === selectedNode.data.type)

    if (!config) return null

    // 如果是 LLM 组件，动态替换 provider 选项
    if (config.type === "llm" && providers.length > 0) {
      const providerOptions = providersToOptions(providers)
      const updatedConfig = {
        ...config,
        inputs: config.inputs.map((input) => {
          if (input.name === "provider") {
            return {
              ...input,
              options: providerOptions,
            }
          }
          return input
        }),
      }
      return updatedConfig
    }

    return config
  }, [selectedNode, providers])

  const handleNodeClick = useCallback(
    (_: React.MouseEvent, node: Node) => {
      setSelectedNodeId(node.id)
    },
    [setSelectedNodeId],
  )

  const updateNodeData = useCallback(
    (nodeId: string, newData: Partial<any>) => {
      setNodes((nds) =>
        nds.map((node) => {
          if (node.id === nodeId) {
            return {
              ...node,
              data: {
                ...node.data,
                ...newData,
              },
            }
          }
          return node
        }),
      )
    },
    [setNodes],
  )

  const handleParameterChange = useCallback(
    (nodeId: string, parameterValues: any) => {
      updateNodeData(nodeId, { parameterValues })
    },
    [updateNodeData],
  )

  if (!mounted || isLoading) {
    return (
      <div className="h-[calc(100vh-8rem)] flex items-center justify-center">
        <div className="text-center space-y-2">
          <div className="h-8 w-8 border-4 border-primary border-t-transparent rounded-full animate-spin mx-auto" />
          <p className="text-sm text-muted-foreground">加载中...</p>
        </div>
      </div>
    )
  }

  return (
    <div className="h-[calc(100vh-8rem)] flex flex-col gap-4">
      {/* Toolbar */}
      <div className="flex items-center justify-between">
        <div className="flex items-center gap-4">
          <Input
            value={agentName}
            onChange={(e) => setAgentName(e.target.value)}
            className="w-64 font-semibold"
            disabled={viewMode === "view"}
          />
          <Badge variant="outline" className="gap-1">
            <Brain className="h-3 w-3" />
            LangGraph Agent
          </Badge>
          <Button
            variant="outline"
            size="sm"
            onClick={() => setViewMode(viewMode === "edit" ? "view" : "edit")}
          >
            {viewMode === "edit" ? (
              <>
                <Eye className="mr-2 h-4 w-4" />
                查看模式
              </>
            ) : (
              <>
                <Edit3 className="mr-2 h-4 w-4" />
                编辑模式
              </>
            )}
          </Button>
        </div>
        <div className="flex items-center gap-2">
          <Button variant="outline" size="sm" onClick={handleViewGeneratedCode}>
            <Code2 className="mr-2 h-4 w-4" />
            查看分层代码
          </Button>
          <Button variant="outline" onClick={handleTest}>
            <Play className="mr-2 h-4 w-4" />
            测试
          </Button>
          {viewMode === "edit" && (
            <Button onClick={handleSave}>
              <Save className="mr-2 h-4 w-4" />
              保存
            </Button>
          )}
        </div>
      </div>

      {/* Main Content */}
      <div className="flex-1 grid grid-cols-[280px_1fr_360px] gap-4 min-h-0">
        {/* Component Library */}
        {viewMode === "edit" && (
          <Card className="flex flex-col">
            <CardHeader className="pb-3">
              <CardTitle className="text-base">组件库</CardTitle>
              <CardDescription>拖拽组件到画布</CardDescription>
            </CardHeader>
            <CardContent className="flex-1 p-0">
              <ScrollArea className="h-full px-4 pb-4">
                <div className="space-y-4">
                  {["核心", "工具", "控制"].map((category) => (
                    <div key={category} className="space-y-2">
                      <h4 className="text-sm font-medium text-muted-foreground">{category}</h4>
                      <div className="grid grid-cols-2 gap-2">
                        {agentComponentConfigs
                          .filter((config) => config.category === category)
                          .map((config) => {
                            const IconComponent = iconMap[config.iconName]
                            return (
                              <div
                                key={config.id}
                                draggable
                                onDragStart={(e) => onDragStart(e, config)}
                                className="group flex flex-col gap-2 p-2.5 rounded-lg border bg-card hover:bg-accent cursor-move transition-colors min-h-[80px]"
                              >
                                <div className="flex items-center gap-2">
                                  <div className="h-7 w-7 rounded-md bg-primary/10 flex items-center justify-center flex-shrink-0">
                                    <IconComponent className="h-3.5 w-3.5 text-primary" />
                                  </div>
                                  <span className="text-xs font-medium leading-tight">{config.label}</span>
                                </div>
                                {config.description && (
                                  <p className="text-[10px] text-muted-foreground leading-tight opacity-0 group-hover:opacity-100 transition-opacity line-clamp-2">
                                    {config.description}
                                  </p>
                                )}
                              </div>
                            )
                          })}
                      </div>
                    </div>
                  ))}
                </div>
              </ScrollArea>
            </CardContent>
          </Card>
        )}

        {/* Canvas */}
        <Card className={`relative overflow-hidden ${viewMode === "edit" ? "" : "col-span-2"}`}>
          <ReactFlow
            nodes={nodes}
            edges={edges}
            onNodesChange={onNodesChange}
            onEdgesChange={onEdgesChange}
            onConnect={onConnect}
            onDrop={onDrop}
            onDragOver={onDragOver}
            onNodeClick={handleNodeClick}
            nodeTypes={nodeTypes}
            fitView
            nodesDraggable={viewMode === "edit"}
            nodesConnectable={viewMode === "edit"}
            elementsSelectable={viewMode === "edit"}
          >
            <Background />
            <Controls />
            <MiniMap
              nodeColor={(node) => {
                const colors: Record<string, string> = {
                  llm: "#a855f7",
                  memory: "#10b981",
                  planner: "#f59e0b",
                  tool: "#8b5cf6",
                  default: "#6b7280",
                }
                return colors[node.data.type] || colors.default
              }}
              maskColor="rgb(0, 0, 0, 0.1)"
            />
            <Panel position="top-left">
              <Badge variant="outline" className="bg-background">
                {viewMode === "edit" ? "编辑模式" : "查看模式"}
              </Badge>
            </Panel>
          </ReactFlow>
        </Card>

        {/* Properties Panel */}
        {viewMode === "edit" && (
          <Card className="flex flex-col">
            <CardHeader className="pb-3">
              <CardTitle className="text-base">组件配置</CardTitle>
              <CardDescription>配置选中组件</CardDescription>
            </CardHeader>
            <CardContent className="flex-1">
              {selectedNode && selectedNodeConfig ? (
                <ScrollArea className="h-full pr-4">
                  <div className="space-y-4">
                    {/* 基本信息 */}
                    <div className="space-y-3">
                      <div className="space-y-2">
                        <Label>组件名称</Label>
                        <Input
                          value={selectedNode.data.label}
                          onChange={(e) => {
                            updateNodeData(selectedNode.id, { label: e.target.value })
                          }}
                        />
                      </div>
                      <div className="space-y-2">
                        <Label>组件类型</Label>
                        <Input value={selectedNodeConfig.label} disabled />
                      </div>
                      {selectedNodeConfig.description && (
                        <div className="flex gap-2 p-2 rounded-md bg-muted/50">
                          <Info className="h-4 w-4 text-muted-foreground shrink-0 mt-0.5" />
                          <p className="text-xs text-muted-foreground">{selectedNodeConfig.description}</p>
                        </div>
                      )}
                    </div>

                    <Separator />

                    {/* 输入参数 */}
                    {selectedNodeConfig.inputs.length > 0 && (
                      <NodeParameterEditor
                        parameters={selectedNodeConfig.inputs}
                        values={selectedNode.data.parameterValues || {}}
                        onChange={(values) => handleParameterChange(selectedNode.id, values)}
                        title="输入参数"
                        type="input"
                      />
                    )}

                    {/* 输出参数 */}
                    {selectedNodeConfig.outputs.length > 0 && (
                      <ParameterList parameters={selectedNodeConfig.outputs} title="输出参数" />
                    )}
                  </div>
                </ScrollArea>
              ) : (
                <div className="flex items-center justify-center h-full text-sm text-muted-foreground text-center px-4">
                  <div className="space-y-2">
                    <p>选择一个组件查看配置</p>
                    <p className="text-xs">点击组件可查看和编辑其属性</p>
                  </div>
                </div>
              )}
            </CardContent>
          </Card>
        )}
      </div>
    </div>
  )
}
